﻿// CTabDevice.cpp: 实现文件
//

#include "pch.h"
#include "DntDemo.h"
#include "afxdialogex.h"
#include "CTabDevice.h"
#include "CTabDdns.h"
#include "TxtUtils.h"
#include "DiffBkTx.h"
#include "DntTest.h"
#define TAG	"TabDevice"

// CTabDevice 对话框

IMPLEMENT_DYNAMIC(CTabDevice, CDialogEx)

CTabDevice::CTabDevice(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_TAB_DEVICE, pParent)
{
}

CTabDevice::~CTabDevice()
{
}

void CTabDevice::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CTabDevice, CDialogEx)
	ON_WM_TIMER()
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, &CTabDevice::OnNMCustomdrawSlider1)
	ON_BN_CLICKED(IDC_BUTTON_RANDOM, &CTabDevice::OnBnClickedButtonRandom)
	ON_BN_CLICKED(IDC_BUTTON_LOGIN, &CTabDevice::OnBnClickedButtonLogin)
	ON_BN_CLICKED(IDC_BUTTON_EVID, &CTabDevice::OnBnClickedButtonEvId)
	ON_BN_CLICKED(IDC_BUTTON_CHANGE, &CTabDevice::OnBnClickedButtonChange)
	ON_BN_CLICKED(IDC_CHECK1, &CTabDevice::OnBnClickedCheck1)
	ON_EN_CHANGE(IDC_EDIT_REG_SIZE, &CTabDevice::OnEnChangeEditReg)
	ON_EN_CHANGE(IDC_EDIT_REG_ADDR, &CTabDevice::OnEnChangeEditReg)
	ON_EN_CHANGE(IDC_EDIT_REG_DATA, &CTabDevice::OnEnChangeEditReg)
	ON_EN_SETFOCUS(IDC_EDIT_REG_SIZE, &CTabDevice::OnEnChangeEditReg)
	ON_EN_SETFOCUS(IDC_EDIT_REG_ADDR, &CTabDevice::OnEnChangeEditReg)
	ON_EN_SETFOCUS(IDC_EDIT_REG_DATA, &CTabDevice::OnEnChangeEditReg)
END_MESSAGE_MAP()


// CTabDevice 消息处理程序

extern CTabDevice* mTabDevice;
static bool isChangReg;
static bool isChangFunc;
static int gChangEdit;
static int gRegAddr;

extern "C" static void changRegCallback() {
	if (mTabDevice != NULL) {
		mTabDevice->ShowRegister();
	}
}
extern "C" static void loginOkCallback() {
	if (mTabDevice != NULL) {
		mTabDevice->ShowRegister();
	}

}
extern "C" static void evalAcctCallback(char* text) {
	if (text != NULL) {										// 申请评估账号Evaluation Account
		int length = (int)strlen(text);
		char* texts[8];
		int qty = TxtKeyArray((size_t*)texts, (char*)text, length - 1, '&', 1);
		if (qty >= 3) {
			CLOGD(TAG, "EvaluateIdCall qty %d %d{%s}", qty, length, text);
			DbsSetMemText("an_1", texts[0]);
			DbsSetMemText("ap_1", texts[1]);
			DbsSetMemText("gv_1", texts[2]);
			if (mTabDevice != NULL) {
				mTabDevice->ShowAccount(false);
			}
			return;
		}
	}
}
BOOL CTabDevice::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	char path[MAX_PATH];
	DbsGetExePath(path, sizeof(path), true);
	TxtFormat(mMyRegPath, sizeof(mMyRegPath), "%s.bin", path);
	isChangReg = false;
	isChangFunc = false;
	gChangEdit = 0;

	int ownerMem = DbsGetMemValue("ownerMem");
	((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(ownerMem);
	uint16_t regSize = DbsGetMemValue("regSize");
	if (ownerMem) {
		uint8_t* myReg = mTEST.MyReg;
		DbsFileRead(mMyRegPath, myReg, sizeof(mTEST.MyReg));
		CLOGD(TAG, "MyReg Read");
		if (regSize < 4 || regSize > APP_REGISTER_SIZE) {
			regSize = 128;
			DbsSetMemValue("regSize", regSize);
		}
	}
	CString text;
	text.Format(L"%u", regSize);
	((CEdit*)GetDlgItem(IDC_EDIT_REG_SIZE))->SetWindowText(text);
	gRegAddr = DbsGetMemValue("regAddr");
	SetEditHexValue(IDC_EDIT_REG_ADDR, gRegAddr, true);		// 写入HEX数值到CEdit

	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetRange(0, 255);
	
	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetLineSize(100);
	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetTicFreq(10);

	TestChangRegCallback(changRegCallback);
	TestLoginOkCallback(loginOkCallback);

	ShowAccount(true);
	ShowRegister();

	//CFont* font;
	//font = new CFont;
	//font->CreateFont(1,0,0,0,0,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_SWISS,_T("Courier"));
	//((CEdit*)GetDlgItem(IDC_EDIT_REG))->SetFont(font);
	//delete font;
	

	srand((int)GetTickCount64());
	SetTimer(1, 300, NULL);
	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}
void CTabDevice::OnTimer(UINT_PTR nIDEvent){
	CDialogEx::OnTimer(nIDEvent);	

	if (isChangReg) {
		isChangReg = false;
		ShowRegister();
	}
	if (gChangEdit > 0 && ++gChangEdit > 6) {				// 在编辑内容被改变约2秒后
		gChangEdit = 0;
		int regSize = GetEditValue(IDC_EDIT_REG_SIZE, false);
		if (regSize >= 4 && regSize <= APP_REGISTER_SIZE) {
			if (DbsGetMemValue("regSize") != regSize) {
				if (DbsGetMemValue("ownerMem")) {			// 自带记忆 上电覆盖服务器数据
					DbsSetMemValue("regSize", regSize);
					isChangFunc = true;
				}
			}
		}
	}
	if (isChangFunc) {
		uint16_t regSize = DbsGetMemValue("regSize");
		uint16_t msgSize = DbsGetMemValue("msgSize");
		if (DntFunWrite(regSize, msgSize, NULL, 0)) {
			isChangFunc = false;
		}
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CTabDevice::ShowAccount(bool init) {
	char bytes[100];
	DbsGetMemText(bytes, sizeof(bytes), "an_1");
	CString name(bytes);
	DbsGetMemText(bytes, sizeof(bytes), "ap_1");
	CString psw(bytes);
	if (name != L"") {
		DbsGetMemText(bytes, sizeof(bytes), "gv_1");
		CString visit(bytes);
		CString text;
		text.Format(L"an:%s ap:%s gv:%s", name, psw, visit);
		((CEdit*)GetDlgItem(IDC_EDIT_EVID))->SetWindowText(text);
	}
	else if (init) {
		CString text = L"可以从云控域名服务器申请一个评估账号";
		((CEdit*)GetDlgItem(IDC_EDIT_EVID))->SetWindowText(text);
	}
	((CEdit*)GetDlgItem(IDC_EDIT_NAME))->SetWindowText(name);
	((CEdit*)GetDlgItem(IDC_EDIT_PSW))->SetWindowText(psw);

	DbsGetMemText(bytes, sizeof(bytes), "mail");
	CString mail(bytes);
	//((CEdit*)GetDlgItem(IDC_EDIT_MAIL))->SetWindowText(mail);
}
void CTabDevice::ShowRegister() {
	char bytes[8192];
	uint8_t* myReg = mTEST.MyReg;
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	if (info->LoginOk) {
		int ownerMem = DbsGetMemValue("ownerMem");
		if (ownerMem) {
			DbsFileWrite(mMyRegPath, myReg, info->RegSize);
			CLOGD(TAG, "MyReg Write");
		}
	}
//	CLOGD(TAG, "Show Register info->RegSize %d", info->RegSize);

	int offset = 0;
	for (int index = 0; index < info->RegSize; index++) {
		int position = index % 16;
		if (position == 0) {
			bytes[offset++] = '\r';
			bytes[offset++] = '\n';
			bytes[offset++] = TxtHexAscii((uint8_t)(index >> 8));
			bytes[offset++] = TxtHexAscii((uint8_t)index >> 4);
			bytes[offset++] = TxtHexAscii((uint8_t)index);
			bytes[offset++] = 'h';
			bytes[offset++] = ':';
			bytes[offset++] = ' ';
		}
		if (position == 4 || position == 8 || position == 12) {
			bytes[offset++] = ' ';
			bytes[offset++] = ' ';
			bytes[offset++] = ' ';
		}
		bytes[offset++] = ' ';
		bytes[offset++] = TxtHexAscii((uint8_t)myReg[index] >> 4);
		bytes[offset++] = TxtHexAscii((uint8_t)myReg[index]);
	}
	bytes[offset] = 0;
	CString text(bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_REG))->SetWindowText(text);

	uint16_t crcs[1 + 8];
	int length = DiffBkTxMakeCrcs(crcs, myReg, info->RegSize);
	length = length / 2;
	offset = TxtFormat(bytes, 128, "寄存器长度可以设置为2至%u字节共%u块，", APP_REGISTER_SIZE, length - 1);
	offset += TxtFormat(bytes + offset, 128, "当任意端改变数值，所有端都会同步地改变数值。使用sum16及每块crc检测变化\r\n");
	offset += TxtFormat(bytes + offset, 128, "\r\n[0]sum16:%04x [1-%u]crc:\r\n", crcs[0], length - 1);
	for (int index = 1; index < length; index++) {
		offset += TxtFormat(bytes + offset, 64, "%04x ", crcs[index]);
	}
	CString string(bytes);
	((CStatic*)GetDlgItem(IDC_EDIT_TIPS))->SetWindowText(string);
		
	if (gChangEdit == 0) {									// 编辑框有更改时不能写编辑框
		ShowSlider(myReg[gRegAddr]);
	}
}
void CTabDevice::ShowSlider(uint8_t value) {
	SetEditHexValue(IDC_EDIT_REG_DATA, value, false);		// 写入HEX数值到CEdit
	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetPos(value);
}
int CTabDevice::GetEditValue(int nID, bool isHex) {			// 获取CEdit输入的16进制或10进制数值
	CString text;
	((CStatic*)GetDlgItem(nID))->GetWindowText(text);
	char byte32[32];
	TxtUnicodeGbk(byte32, 32, (short*)text.AllocSysString());	// UNICODE转换到GBK
	return isHex ? TxtHexToValue(byte32, 0) : TxtToInt(byte32);		// 文字转换到数值
}
void CTabDevice::SetEditHexValue(int nID, int value, bool three) {		// 写入HEX数值到CEdit
	CString text;
	text.Format(three ? L"%03x" : L"%02x", value);
	((CStatic*)GetDlgItem(nID))->SetWindowText(text);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CTabDevice::OnBnClickedButtonEvId(){
	char bytes[100];
	if (DbsGetMemText(bytes, sizeof(bytes), "an_1") > 0) {
		::AfxMessageBox(L"已经有评估账号，不需要再次申请");
		return;
	}
	CString mail;
	((CEdit*)GetDlgItem(IDC_EDIT_MAIL))->GetWindowText(mail);
	if (mail == L"" || mail.GetLength() < 6) {
		::AfxMessageBox(L"请输入有效的电子邮箱或手机号码");
		return;
	}
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)mail.AllocSysString());		// UNICODE转换到GUTF8
	DbsSetMemText("mail", bytes);
	TestEvalAccount(evalAcctCallback);
}
void CTabDevice::OnBnClickedButtonLogin(){
	char bytes[128];
	CString string;
	((CEdit*)GetDlgItem(IDC_EDIT_NAME))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("an_1", bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_PSW))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("ap_1", bytes);
	if (DbsGetMemText(bytes, sizeof(bytes), "an_1") > 0) {
		if (DbsGetMemText(bytes, sizeof(bytes), "ap_1") > 0) {
			DntSetIdleFlag(DNT_RB_LOGIN);
			return;
		}
		::AfxMessageBox(L"请输入电器设备端的账号密码");
		return;
	}
	::AfxMessageBox(L"请输入电器设备端的账号名");
}
void CTabDevice::OnEnChangeEditReg() {
	gChangEdit = 1;
}

void CTabDevice::OnBnClickedCheck1(){
	DbsSetMemValue("ownerMem", ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck());
}

void CTabDevice::OnNMCustomdrawSlider1(NMHDR* pNMHDR, LRESULT* pResult) {
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);

	int position = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->GetPos();
	uint8_t* regs = mTEST.MyReg;
	//CLOGD(TAG, "Slider RegWrite %03x %02x %02x", gRegAddr, regs[gRegAddr], position);
	regs[gRegAddr] = (uint8_t)position;
	ShowSlider(regs[gRegAddr]);
	if (DntSetIdleFlag(DNT_RB_REG_WR)) {
		isChangReg = true;
		*pResult = 0;
		return;
	}
	*pResult = 0;
}
void CTabDevice::OnBnClickedButtonRandom() {
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	if (info->LoginOk) {
		gRegAddr = rand() % info->RegSize;
		uint8_t value = (uint8_t)rand();
		DbsSetMemValue("regAddr", gRegAddr);
		ShowSlider(value);
		SetEditHexValue(IDC_EDIT_REG_ADDR, gRegAddr, true);		// 写入HEX数值到CEdit
		SetEditHexValue(IDC_EDIT_REG_DATA, value, false);	// 写入HEX数值到CEdit
		return;
	}
	::AfxMessageBox(L"出错");
}

void CTabDevice::OnBnClickedButtonChange() {
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	int regAddr = GetEditValue(IDC_EDIT_REG_ADDR, true);
	if (regAddr < info->RegSize) {
		gRegAddr = regAddr;
		DbsSetMemValue("regAddr", regAddr);
	}

	int value = GetEditValue(IDC_EDIT_REG_DATA, true);			//  获取CEdit输入的16进制或10进制数值
	if (value <= 0x100) {
		SetEditHexValue(IDC_EDIT_REG_DATA, value, false);	// 写入HEX数值到CEdit
		uint8_t* regs = mTEST.MyReg;
		regs[gRegAddr] = (uint8_t)value;
		CLOGD(TAG, "改变寄存器0x%03x的值为0x%02x", gRegAddr, value);
		if (DntSetIdleFlag(DNT_RB_REG_WR)){
			isChangReg = true;
			return;
		}
	}
	::AfxMessageBox(L"出错");
}
